# coding:utf-8
from typing import Union

from PySide6.QtCore import QRect, Qt, Signal, Property
from PySide6.QtGui import QImage, QPainter, QPixmap, QColor, QPainterPath, QKeyEvent
from PySide6.QtWidgets import QWidget


class VideoWidget(QWidget):
    """
    视频播放控件, 该控件只能作为子页面使用, 不能单独使用
    """
    imageChanged = Signal(QImage)
    fullScreenChanged = Signal(bool)

    _topLeftRadius = 0
    _topRightRadius = 0
    _bottomLeftRadius = 0
    _bottomRightRadius = 0

    def __init__(self, parent=None):
        super().__init__(parent)
        self._transparent = False
        self._backgroundColor = Qt.GlobalColor.black
        self.image = QImage()
        self.backgroundImage = QImage()
        self.setBorderRadius(5, 5, 5, 5)
        self.setMouseTracking(True)

    def setPixmap(self, pixmap: QPixmap):
        """ 设置显示的图像 """
        self.setImage(pixmap)

    def pixmap(self) -> QPixmap:
        """ 获取显示的图像 """
        return QPixmap.fromImage(self.image)

    def setImage(self, image: Union[QPixmap, QImage] = None):
        """ 设置显示的图像 """
        self.image = image or QImage()
        if isinstance(image, QPixmap):
            self.image = image.toImage()
        self.imageChanged.emit(self.image)
        self.update()

    def setBackgroundImage(self, image: Union[str, QPixmap, QImage] = None):
        """ 设置背景图像 """
        self.backgroundImage = image or QImage()
        if isinstance(image, QPixmap):
            self.backgroundImage = image.toImage()
            self.update()
        elif isinstance(image, str):
            self.backgroundImage.load(image)
            self.update()

    def backgroundImage(self) -> QImage:
        """ 获取背景图像 """
        return self.backgroundImage

    def isNull(self):
        return self.image.isNull()

    def setTransparent(self, transparent: bool):
        """ 设置是否透明 """
        self._transparent = transparent
        self.update()

    def isTransparent(self) -> bool:
        """ 获取是否透明 """
        return self._transparent

    def setBackgroundColor(self, color: QColor):
        """ 设置背景颜色 """
        self._backgroundColor = color
        self.update()

    def backgroundColor(self) -> QColor:
        """ 获取背景颜色 """
        return self._backgroundColor

    def setBorderRadius(self, topLeft: int, topRight: int, bottomLeft: int, bottomRight: int):
        """ set the border radius of image """
        self._topLeftRadius = topLeft
        self._topRightRadius = topRight
        self._bottomLeftRadius = bottomLeft
        self._bottomRightRadius = bottomRight
        self.update()

    @Property(int)
    def topLeftRadius(self):
        return self._topLeftRadius

    @topLeftRadius.setter
    def topLeftRadius(self, radius: int):
        self.setBorderRadius(radius, self.topRightRadius, self.bottomLeftRadius, self.bottomRightRadius)

    @Property(int)
    def topRightRadius(self):
        return self._topRightRadius

    @topRightRadius.setter
    def topRightRadius(self, radius: int):
        self.setBorderRadius(self.topLeftRadius, radius, self.bottomLeftRadius, self.bottomRightRadius)

    @Property(int)
    def bottomLeftRadius(self):
        return self._bottomLeftRadius

    @bottomLeftRadius.setter
    def bottomLeftRadius(self, radius: int):
        self.setBorderRadius(self.topLeftRadius, self.topRightRadius, radius, self.bottomRightRadius)

    @Property(int)
    def bottomRightRadius(self):
        return self._bottomRightRadius

    @bottomRightRadius.setter
    def bottomRightRadius(self, radius: int):
        self.setBorderRadius(
            self.topLeftRadius,
            self.topRightRadius,
            self.bottomLeftRadius,
            radius
        )

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHints(QPainter.RenderHint.Antialiasing)
        painter.setRenderHint(QPainter.RenderHint.LosslessImageRendering)

        path = QPainterPath()
        w, h = self.width(), self.height()

        # top line
        path.moveTo(self.topLeftRadius, 0)
        path.lineTo(w - self.topRightRadius, 0)

        # top right arc
        d = self.topRightRadius * 2
        path.arcTo(w - d, 0, d, d, 90, -90)

        # right line
        path.lineTo(w, h - self.bottomRightRadius)

        # bottom right arc
        d = self.bottomRightRadius * 2
        path.arcTo(w - d, h - d, d, d, 0, -90)

        # bottom line
        path.lineTo(self.bottomLeftRadius, h)

        # bottom left arc
        d = self.bottomLeftRadius * 2
        path.arcTo(0, h - d, d, d, -90, -90)

        # left line
        path.lineTo(0, self.topLeftRadius)

        # top left arc
        d = self.topLeftRadius * 2
        path.arcTo(0, 0, d, d, -180, -90)

        # 裁剪路径
        painter.setPen(Qt.PenStyle.NoPen)
        painter.setClipPath(path)
        if not self._transparent:
            painter.fillRect(self.rect(), self._backgroundColor)  # 填充颜色
        if not self.backgroundImage.isNull():
            painter.drawImage(self.rect(), self.backgroundImage)  # 填充背景图片

        if self.isNull():
            return

        # draw image
        image = self.image

        # 保持宽高比居中显示
        image_ratio = image.width() / image.height()
        widget_ratio = self.width() / self.height()

        # 计算适配后的显示区域
        if widget_ratio > image_ratio:
            target_width = self.height() * image_ratio
            target_rect = QRect(
                (self.width() - target_width) // 2, 0,
                target_width, self.height()
            )
        else:
            target_height = self.width() / image_ratio
            target_rect = QRect(
                0, (self.height() - target_height) // 2,
                self.width(), target_height
            )

        painter.drawImage(target_rect, image)

    def fullScreen(self):
        """ 全屏显示 """
        self.setWindowFlags(Qt.WindowType.Window)
        self.showFullScreen()
        self.fullScreenChanged.emit(True)

    def normalScreen(self):
        """ 退出全屏显示 """
        self.setWindowFlags(Qt.WindowType.SubWindow)
        self.showNormal()
        self.fullScreenChanged.emit(False)

    def toggleFullScreen(self):
        """ 切换全屏显示 """
        if self.isFullScreen():
            self.normalScreen()
        else:
            self.fullScreen()
            self.setBorderRadius(0, 0, 0, 0)

    def setFullScreen(self, fullScreen: bool):
        """ 设置全屏显示 """
        if fullScreen:
            self.fullScreen()
        else:
            self.normalScreen()

    def keyPressEvent(self, event: QKeyEvent):
        """ 键盘按下事件 """
        if event.key() == Qt.Key.Key_Escape:
            self.toggleFullScreen()
